package com.slipper.ai.flow.support;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.slipper.ai.flow.INodeDealer;
import com.slipper.ai.flow.Parser;
import com.slipper.ai.flow.vo.*;
import com.slipper.core.gson.GsonUtil;
import com.slipper.util.Tool;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component("aiHttpNodeDealer")
public class HttpNodeDealer implements INodeDealer {
    @Override
    public String getType() {
        return NodeVO.TYPE_HTTP;
    }

    @Override
    public List<LineVO> doDeal(FlowVO flow, NodeVO node, NodeInstVO nodeInst) {
        if (!(node instanceof HttpNodeVO httpNode)) throw new RuntimeException("节点类型不正确！");
        if (Tool.isBlank(httpNode.getUrl())) throw new RuntimeException("请求地址不能为空！");

        HttpRequest request = switch (httpNode.getMethod()) {
            case "GET" -> HttpRequest.get(httpNode.getUrl());
            case "PUT" -> HttpRequest.put(httpNode.getUrl());
            case "DELETE" -> HttpRequest.delete(httpNode.getUrl());
            default -> HttpRequest.post(httpNode.getUrl());
        };

        if (httpNode.getHeaderList() != null && !httpNode.getHeaderList().isEmpty()) {
            Map<String, String> headerMap = new HashMap<>();
            httpNode.getHeaderList().forEach(header -> headerMap.put(
                    header.getName(),
                    Parser.parseSymbol(header.getValue(), nodeInst.getInput())
            ));

            if ("json".equals(httpNode.getBodyType())
                    && headerMap.keySet().stream().noneMatch(item -> item.equalsIgnoreCase("Content-Type"))) {
                headerMap.put("Content-Type", "application/json");
            }
            request.clearHeaders();
            request.addHeaders(headerMap);
        }

        switch (httpNode.getBodyType()) {
            case "json": {
                Map<String, String> paramMap = new HashMap<>();
                if (httpNode.getParamList() != null && !httpNode.getParamList().isEmpty()) {
                    httpNode.getParamList().forEach(param -> paramMap.put(
                            param.getName(),
                            Parser.parseSymbol(param.getValue(), nodeInst.getInput())
                    ));
                }
                request.body(GsonUtil.toJson(paramMap));
                break;
            }
            case "raw": {
                request.body(httpNode.getBody());
                break;
            }
            default: {
                if (httpNode.getParamList() != null && !httpNode.getParamList().isEmpty()) {
                    httpNode.getParamList().forEach(param -> request.form(
                            param.getName(),
                            Parser.parseSymbol(param.getValue(), nodeInst.getInput())
                    ));
                }
            }
        }

        HttpResponse response = request
                .setConnectionTimeout(60 * 1000)
                .setReadTimeout(60 * 1000)
                .execute();

        String body = response.body();
        Map<String, Object> outputMap = new HashMap<>();
        outputMap.put("请求返回结果", body);
        outputMap.put("请求返回状态码", response.getStatus());

        if (httpNode.getOutputList() != null && !httpNode.getOutputList().isEmpty()) {
            List<ParamVO> outputList = httpNode.getOutputList()
                    .stream()
                    .filter(item -> item.getBuiltin() == null || !item.getBuiltin())
                    .toList();
            if (!outputList.isEmpty()) {
                try {
                    Map<String, Object> dataMap = GsonUtil.toMap(body);
                    if (dataMap != null && !dataMap.isEmpty()) {
                        outputList.forEach(param -> {
                            String[] keys = param.getName().split("\\.");
                            Object value = dataMap;
                            for (int i = 1; i < keys.length; i++) {
                                String key = keys[i];
                                if (value instanceof Map<?, ?> map) {
                                    value = map.get(key);
                                }
                            }
                            outputMap.put(param.getName(), value == null ? "" : value.toString());
                        });
                    }
                } catch (Exception ignored) {}
            }
        }
        nodeInst.setOutput(outputMap);

        response.close();
        return flow.getLines()
                .stream()
                .filter(line -> line.getSource().equals(node.getId()))
                .collect(Collectors.toList());
    }
}
